#tag Class
Protected Class DecissionTree
Implements ArtificialPlayer
	#tag Method, Flags = &h0
		Sub Constructor(p as game . Player)
		  self.player = p
		  self.game = p.GetGame
		  self.board = game.GetBoard
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h0
		Sub Calculate()
		  //do nothing yet
		  dim possibleCoordsNorth() as coordinates
		  dim possibleCoordsEast() as coordinates
		  dim possibleCoordsSouth() as coordinates
		  dim possibleCoordsWest() as coordinates
		  dim positions() as Evaluator
		  dim pos as Coordinates
		  dim i as integer
		  dim j as integer
		  dim dbg as string
		  dim theTile as board.Tile
		  dim noOfTiles as Integer
		  dim myTowns() as game.Tile
		  dim myStreets() as game.Tile
		  dim tilesRemaining as Integer
		  
		  
		  theTile = game.GetNextTile
		  
		  
		  tilesRemaining = ubound(game.GetRemainingTiles) + 1
		  //update my property
		  for i = 0 to UBound(game.towns)
		    if game.towns(i).getOwner <> nil then
		      dim name as String
		      dim owner as game.player
		      owner = game.towns(i).getOwner
		      name = owner.GetName
		      
		      if  name = player.GetName then
		        myTowns.Append  game.towns(i)
		      end if
		    end if
		  next
		  
		  for i = 0 to UBound(game.streets)
		    if game.streets(i).getOwner <> nil then
		      dim name as String
		      dim owner as game.player
		      owner = game.streets(i).getOwner
		      name = owner.GetName
		      if name = player.GetName then
		        myStreets.Append game.streets(i)
		      end if
		    end if
		  next
		  
		  possibleCoordsNorth = game.GetPossibleCoordinatesForTile()
		  theTile.rotateClockwise
		  possibleCoordsEast = game.GetPossibleCoordinatesForTile()
		  theTile.rotateClockwise
		  possibleCoordsSouth  = game.GetPossibleCoordinatesForTile()
		  theTile.rotateClockwise
		  possibleCoordsWest  = game.GetPossibleCoordinatesForTile()
		  theTile.rotateClockwise //set it back
		  
		  
		  select case theTile.type
		    
		    //if tile is a monastery of type A
		    //if theTile.type = "MonasteryA" then
		  case "MonasteryA"
		    if ubound(possibleCoordsNorth) > -1 then //all sides are the same
		      for i = 0 to UBound(possibleCoordsNorth)
		        dim neighbors as integer
		        neighbors = GetNumberOfNeighbors(possibleCoordsNorth(i))
		        dim ev as new Evaluator
		        ev.tileState = "north"
		        ev.xy = possibleCoordsNorth(i)
		        ev.pos = "c"
		        ev.AddValue 1
		        if neighbors = 9 then
		          ev.AddValue 10
		        end if
		        if neighbors >=5 and neighbors < 9 then
		          ev.AddValue 5
		        end if
		        if tilesRemaining < 15 then
		          ev.addValue 5
		        end if
		        positions.Append ev
		      next
		    end if
		  case "MonasteryB"
		    //monastery is of type b
		    if ubound(possibleCoordsNorth) > -1 then //all sides are the same
		      for i = 0 to UBound(possibleCoordsNorth)
		        dim neighbors as integer
		        neighbors = GetNumberOfNeighbors(possibleCoordsNorth(i))
		        dim ev as new Evaluator
		        ev.tileState = "north"
		        ev.xy = possibleCoordsNorth(i)
		        ev.pos = "c"
		        if neighbors = 9 then
		          ev.AddValue 10
		        end if
		        if neighbors >=5 and neighbors < 9 then
		          ev.AddValue 5
		        end if
		        if tilesRemaining < 15 then
		          ev.addValue 5
		        end if
		        positions.Append ev
		      next
		    end if
		    //EastIsOnTopState
		    if ubound(possibleCoordsEast) > -1 then //all sides are the same
		      for i = 0 to UBound(possibleCoordsEast)
		        dim neighbors as integer
		        neighbors = GetNumberOfNeighbors(possibleCoordsEast(i))
		        dim ev as new Evaluator
		        ev.tileState = "east"
		        ev.xy = possibleCoordsEast(i)
		        ev.pos = "c"
		        if neighbors = 9 then
		          ev.AddValue 10
		        end if
		        if neighbors < 9 and neighbors >= 5 then
		          ev.AddValue 5
		        end if
		        if neighbors <=5 and neighbors >=3 then
		          ev.AddValue 1
		        end if
		        if tilesRemaining < 15 then
		          ev.addValue 5
		        end if
		        positions.Append ev
		      next
		    end if
		    //SouthIsOnTopState
		    if ubound(possibleCoordsSouth) > -1 then //all sides are the same
		      for i = 0 to UBound(possibleCoordsSouth)
		        dim neighbors as integer
		        neighbors = GetNumberOfNeighbors(possibleCoordsSouth(i))
		        dim ev as new Evaluator
		        ev.tileState = "south"
		        ev.xy = possibleCoordsSouth(i)
		        ev.pos = "c"
		        if neighbors = 9 then
		          ev.AddValue 10
		        end if
		        if neighbors < 9 and neighbors >= 5 then
		          ev.AddValue 5
		        end if
		        if neighbors <=5 and neighbors >=3 then
		          ev.AddValue 1
		        end if
		        if tilesRemaining < 15 then
		          ev.addValue 5
		        end if
		        positions.Append ev
		      next
		    end if
		    //WestIsOnTopState
		    if ubound(possibleCoordsWest) > -1 then
		      for i = 0 to UBound(possibleCoordsWest)
		        dim neighbors as integer
		        neighbors = GetNumberOfNeighbors(possibleCoordsWest(i))
		        dim ev as new Evaluator
		        ev.tileState = "north"
		        ev.xy = possibleCoordsWest(i)
		        ev.pos = "c"
		        if neighbors = 9 then
		          ev.AddValue 10
		        end if
		        if neighbors < 9 and neighbors >=5 then
		          ev.AddValue 5
		        end if
		        if neighbors <=5 and neighbors >=3 then
		          ev.AddValue 1
		        end if
		        if tilesRemaining < 15 then
		          ev.addValue 5
		        end if
		        positions.Append ev
		      next
		    end if
		    //end if
		  else
		    //towns or streets
		    
		    for i = 0 to ubound(possibleCoordsNorth)
		      dim ev as new Evaluator
		      ev.tileState = "north"
		      ev.xy = possibleCoordsNorth(i)
		      
		      if board.GetPositionIsOccupieableTown(possibleCoordsNorth(i), player) or _
		        board.GetPositionIsOccupieableStreet(possibleCoordsNorth(i), player) then
		        dim possibleSlots() as board.slot
		        possibleSlots  = game.GetCurrentTile.grid.GetPossibleSlots
		        ev.addValue 5
		        if theTile.coatOfArms = true then
		          ev.addValue 5
		        end if
		        if ubound(possibleSlots) > -1 then
		          if theTile.type = "TownA" then
		            ev.addValue 5
		          end if
		          if theTile.type = "TownN" or theTile.type = "TownO" or _
		            theTile.type = "TownP" or theTile.type = "TownQ"  or _
		            theTile.type = "TownR" then
		            dim helper as Coordinates
		            helper.x = possibleCoordsNorth(i).x
		            helper.y = possibleCoordsNorth(i).y +1
		            dim helpTile as Tile
		            helpTile = board.getTileByPosition(helper)
		            
		            if helpTile <> nil then
		              if helpTile.isSingleTown then
		                ev.addValue 30
		              end if
		            else
		              ev.addValue 10
		            end if
		          end if
		          
		          
		          for j = 0 to ubound (possibleSlots)
		            if theTile.type.left(4) = "Town" then
		              if possibleSlots(j).GetType = "Town" then
		                ev.pos = possibleSlots(j).GetPosition
		                exit for
		              end if
		            else
		              if theTile.type.left(6) = "Grassl" then
		                if possibleSlots(j).GetType = "Street" then
		                  ev.pos = possibleSlots(j).GetPosition
		                  exit for
		                end if
		              end if
		            end if
		          next
		        end if
		      end if
		      positions.Append ev
		    next
		    
		    for i = 0 to ubound(possibleCoordsEast)
		      dim ev as new Evaluator
		      ev.tileState = "east"
		      ev.xy = possibleCoordsEast(i)
		      
		      if board.GetPositionIsOccupieableTown(possibleCoordsEast(i), player) or _
		        board.GetPositionIsOccupieableStreet(possibleCoordsEast(i), player) then
		        dim possibleSlots() as board.slot
		        possibleSlots  = game.GetCurrentTile.grid.GetPossibleSlots
		        ev.addValue 5
		        if theTile.coatOfArms = true then
		          ev.addValue 5
		        end if
		        if ubound(possibleSlots) > -1 then
		          if theTile.type = "TownA" then
		            ev.addValue 5
		          end if
		          if theTile.type = "TownN" or theTile.type = "TownO" or _
		            theTile.type = "TownP" or theTile.type = "TownQ"  or _
		            theTile.type = "TownR" then
		            dim helper as Coordinates
		            helper.x = possibleCoordsEast(i).x -1
		            helper.y = possibleCoordsEast(i).y
		            dim helpTile as Tile
		            helpTile = board.getTileByPosition(helper)
		            
		            if helpTile <> nil then
		              if helpTile.isSingleTown then
		                ev.addValue 30
		              end if
		            else
		              ev.addValue 10
		            end if
		          end if
		          
		          for j = 0 to ubound (possibleSlots)
		            if theTile.type.left(4) = "Town" then
		              if possibleSlots(j).GetType = "Town" then
		                ev.pos = possibleSlots(j).GetPosition
		                exit for
		              end if
		            else
		              if theTile.type.left(6) = "Grassl" then
		                if possibleSlots(j).GetType = "Street" then
		                  ev.pos = possibleSlots(j).GetPosition
		                  exit for
		                end if
		              end if
		            end if
		          next
		        end if
		      end if
		      positions.Append ev
		    next
		    
		    for i = 0 to ubound(possibleCoordsSouth)
		      dim ev as new Evaluator
		      ev.tileState = "south"
		      ev.xy = possibleCoordsSouth(i)
		      
		      if board.GetPositionIsOccupieableTown(possibleCoordsSouth(i), player) or _
		        board.GetPositionIsOccupieableStreet(possibleCoordsSouth(i), player) then
		        dim possibleSlots() as board.slot
		        possibleSlots  = game.GetCurrentTile.grid.GetPossibleSlots
		        ev.addValue 5
		        if theTile.coatOfArms = true then
		          ev.addValue 5
		        end if
		        if ubound(possibleSlots) > -1 then
		          if theTile.type = "TownA" then
		            ev.addValue 5
		          end if
		          
		          if theTile.type = "TownN" or theTile.type = "TownO" or _
		            theTile.type = "TownP" or theTile.type = "TownQ"  or _
		            theTile.type = "TownR" then
		            dim helper as Coordinates
		            helper.x = possibleCoordsSouth(i).x
		            helper.y = possibleCoordsSouth(i).y - 1
		            dim helpTile as Tile
		            helpTile = board.getTileByPosition(helper)
		            
		            if helpTile <> nil then
		              if helpTile.isSingleTown then
		                ev.addValue 30
		              end if
		            else
		              ev.addValue 10
		            end if
		          end if
		          
		          
		          for j = 0 to ubound (possibleSlots)
		            if theTile.type.left(4) = "Town" then
		              if possibleSlots(j).GetType = "Town" then
		                ev.pos = possibleSlots(j).GetPosition
		                exit for
		              end if
		            else
		              if theTile.type.left(6) = "Grassl" then
		                if possibleSlots(j).GetType = "Street" then
		                  ev.pos = possibleSlots(j).GetPosition
		                  exit for
		                end if
		              end if
		            end if
		          next
		        end if
		      end if
		      positions.Append ev
		    next
		    
		    for i = 0 to ubound(possibleCoordsWest)
		      dim ev as new Evaluator
		      ev.tileState = "west"
		      ev.xy = possibleCoordsWest(i)
		      
		      if board.GetPositionIsOccupieableTown(possibleCoordsWest(i), player) or _
		        board.GetPositionIsOccupieableStreet(possibleCoordsWest(i), player) then
		        dim possibleSlots() as board.slot
		        possibleSlots  = game.GetCurrentTile.grid.GetPossibleSlots
		        ev.addValue 5
		        if theTile.coatOfArms = true then
		          ev.addValue 5
		        end if
		        if ubound(possibleSlots) > -1 then
		          if theTile.type = "TownA" then
		            ev.addValue 5
		          end if
		          if theTile.type = "TownN" or theTile.type = "TownO" or _
		            theTile.type = "TownP" or theTile.type = "TownQ"  or _
		            theTile.type = "TownR" then
		            dim helper as Coordinates
		            helper.x = possibleCoordsWest(i).x +1
		            helper.y = possibleCoordsWest(i).y
		            dim helpTile as Tile
		            helpTile = board.getTileByPosition(helper)
		            
		            if helpTile <> nil then
		              if helpTile.isSingleTown then
		                ev.addValue 30
		              end if
		            else
		              ev.addValue 10
		            end if
		          end if
		          for j = 0 to ubound (possibleSlots)
		            if theTile.type.left(4) = "Town" then
		              if possibleSlots(j).GetType = "Town" then
		                ev.pos = possibleSlots(j).GetPosition
		                exit for
		              end if
		            else
		              if theTile.type.left(6) = "Grassl" then
		                if possibleSlots(j).GetType = "Street" then
		                  ev.pos = possibleSlots(j).GetPosition
		                  exit for
		                end if
		              end if
		            end if
		          next
		        end if
		      end if
		      positions.Append ev
		    next
		  end select
		  
		  
		  
		  
		  //place it on board
		  dim index as integer = 0
		  dim highest as integer = -1
		  dim theOne as Evaluator
		  for i = 0 to ubound(positions)
		    if positions(i).GetValue > highest then
		      theOne = positions(i)
		      highest = theOne.GetValue
		    end if
		  next
		  
		  //we have to rotate the gametile into the correct position
		  //north doesn't need that as the tile should be in northposition
		  if theOne.tileState = "east" then
		    theTile.rotateClockwise
		  end if
		  if theOne.tileState = "south" then
		    theTile.rotateClockwise
		    theTile.rotateClockwise
		  end if
		  if theOne.tileState = "west" then
		    theTile.rotateCounterclockwise
		  end if
		  
		  call player.AddtileAtPosition(theTile, theOne.xy)
		  dbg = player.getName + " addTile " + theTile.GetUid + " at position " + str(theOne.xy.x) + "/" + str(theOne.xy.y)
		  
		  //decide if to place a gamepiece - the ai off course only sets a gamepiece
		  //if it still has pieces left and if the evaluated position has a value of
		  //10 or greater. If it still has gamepieces more than 5 gamepieces left
		  //it also places a gamepiece
		  if player.hasGamepieces then
		    if theOne.GetValue >= 10 or player.GetNumberOfGamepieces > 5 then
		      if theOne.pos.len > 0 then
		        player.occupy theOne.pos
		        dbg = dbg + " occupies " + theOne.pos
		      end if
		    end if
		  else
		    dbg = dbg + " has no more gamepieces left "
		  end if
		  
		  App.Dbg = App.Dbg + dbg + EndOfLine
		  app.Dbg = app.Dbg + player.GetName + " Score: " + str(player.getscore) + EndOfLine
		  
		  player.EndRound
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h21
		Private Function GetNumberOfNeighbors(position as coordinates) As Integer
		  dim pos as Coordinates
		  dim number as integer = 0
		  dim board as board.GameBoard
		  
		  board = game.GetBoard
		  
		  //x..
		  //...
		  //...
		  pos.x = position.x -1
		  pos.y = position.y +1
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //.x.
		  //...
		  //...
		  pos.x = position.x
		  pos.y = position.y +1
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //..x
		  //...
		  //...
		  pos.x = position.x +1
		  pos.y = position.y +1
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //x..
		  //...
		  pos.x = position.x -1
		  pos.y = position.y
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //..x
		  //...
		  pos.x = position.x +1
		  pos.y = position.y
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //...
		  //x..
		  pos.x = position.x -1
		  pos.y = position.y -1
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //...
		  //.x.
		  pos.x = position.x
		  pos.y = position.y -1
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  //...
		  //...
		  //..x
		  pos.x = position.x +1
		  pos.y = position.y -1
		  
		  if board.GetTileByPosition(pos) <> nil then
		    number = number + 1
		  end if
		  
		  return number
		End Function
	#tag EndMethod


	#tag Property, Flags = &h0
		player As game.Player
	#tag EndProperty

	#tag Property, Flags = &h0
		game As game.ConcreteGame
	#tag EndProperty

	#tag Property, Flags = &h0
		board As board.Gameboard
	#tag EndProperty


	#tag ViewBehavior
		#tag ViewProperty
			Name="Name"
			Visible=true
			Group="ID"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Index"
			Visible=true
			Group="ID"
			InitialValue="-2147483648"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Super"
			Visible=true
			Group="ID"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Left"
			Visible=true
			Group="Position"
			InitialValue="0"
			InheritedFrom="Object"
		#tag EndViewProperty
		#tag ViewProperty
			Name="Top"
			Visible=true
			Group="Position"
			InitialValue="0"
			InheritedFrom="Object"
		#tag EndViewProperty
	#tag EndViewBehavior
End Class
#tag EndClass
